<?php

namespace Tests;

use Illuminate\Support\Facades\DB;
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;

abstract class TestCase extends BaseTestCase
{
    use CreatesApplication;

    //单测输出SQL
    protected $queries = [];

    /**
     * 在每个测试之前调用.
     */
    protected function setUp(): void
    {
        parent::setUp();

        // 监听 SQL 查询
        DB::listen(
            function ($sql) {
                foreach ($sql->bindings as $i => $binding) {
                    if ($binding instanceof \DateTime) {
                        $sql->bindings[$i] = $binding->format('\'Y-m-d H:i:s\'');
                    } else {
                        if (is_string($binding)) {
                            $sql->bindings[$i] = "$binding";
                        }
                    }
                }

                $query = str_replace(['%', '?'], ['%%', '%s'], $sql->sql);
                $query = vsprintf($query, $sql->bindings);
                $this->queries[] = $query;
            }
        );
    }

    /**
     * 在每个测试后调用.
     */
    protected function tearDown(): void
    {
        // 输出所有执行过的 SQL 查询
        foreach ($this->queries as $query) {
            echo $query . ';' . "\n";
        }

        parent::tearDown();
    }
}

if (!function_exists('debug_sql')) {
    /**
     * 调试sql.
     *
     * @param callable $state
     * @param bool     $commit   是否提交，否则回滚事务
     * @param bool     $withTime
     *
     * @return array
     */
    function debug_sql(callable $state, bool $commit = true, bool $withTime = false)
    {
        DB::enableQueryLog();
        $state();
        $queryLog = DB::getQueryLog();
        if (!$commit) {
            DB::rollBack();
        }
        DB::disableQueryLog();
        $res = collect($queryLog)->map(function ($item) use ($withTime) {
            foreach ($item['bindings'] as $bVal) {
                $item['query'] = substr_replace($item['query'], is_string($bVal) ? "'" . $bVal . "'" : $bVal, strpos($item['query'], '?'), 1);
            }
            $item['query'] .= $withTime ? ' /*' . $item['time'] . 'ms*/' : ';';

            return $item['query'];
        })->toArray();
        dump($res);

        return $res;
    }
}
